/**************************************************************************//**
 * @item     CosyOS-III Port
 * @file     port_cmx_s.c
 * @brief    CMSIS Cortex-M Core Port File for Arm / GNU / IAR Compiler
 * @author   迟凯峰
 * @version  V1.0.4
 * @date     2025.05.18
 ******************************************************************************/

#include "os_var.h"
#ifdef __PORT_CMX_H

#if ((defined (__ARM_ARCH_7M__       ) && (__ARM_ARCH_7M__        == 1)) \
 ||  (defined (__ARM_ARCH_7EM__      ) && (__ARM_ARCH_7EM__       == 1)) \
 ||  (defined (__ARM_ARCH_8M_BASE__  ) && (__ARM_ARCH_8M_BASE__   == 1)) \
 ||  (defined (__ARM_ARCH_8M_MAIN__  ) && (__ARM_ARCH_8M_MAIN__   == 1)) \
 ||  (defined (__ARM_ARCH_8_1M_MAIN__) && (__ARM_ARCH_8_1M_MAIN__ == 1)))
#define __CMX_ISA 7
#else
#define __CMX_ISA 6
#endif


/*
 * Arm Compiler 4/5
 */
#if (defined ( __CC_ARM ))

/* PendSV软中断 */
__ASM void OS_PendSV_Handler(void)
{
                IMPORT  sPendSV_Handler
                IMPORT  s_task_current
                PRESERVE8
                THUMB

                push    {lr}
                bl      sPendSV_Handler
/* 直接返回吗？*/
                #if (__CMX_ISA == 6)
                cmp     r0, #0
                beq     __RETURN
                #else
                cbz     r0, __RETURN
                #endif
                isb
/* 保护现场吗？*/
                ldr     r1, =s_task_current
                subs    r0, #1
                #if (__CMX_ISA == 6)
                cmp     r0, #0
                beq     __RESTORE
                #else
                cbz     r0, __RESTORE
                #endif
                mrs     r0, psp
/* 任务PC监控 */
                #if (SYSCFG_TASKPC_MONITOR == 1)
                IMPORT  s_sign_taskmgr
                IMPORT  s_pc
                ldr     r2, =s_sign_taskmgr
                ldrb    r2, [r2]
                #if (__CMX_ISA == 6)
                cmp     r2, #0
                beq     __PROTECTING
                #else
                cbz     r2, __PROTECTING
                #endif
                ldr     r2, [r0,#24]
                push    {r3}
                ldr     r3, =s_pc
                str     r2, [r3]
                pop     {r3}
                #endif
/* 保护现场 */
__PROTECTING
                #if (MCUCFG_ASPEN_LSPEN == 1)
                vstmdb  r0!, {s16-s31}
                #endif
                #if (__CMX_ISA == 6)
                subs    r0, #32
                ldr     r2, [r1]
                str     r0, [r2]
                stmia   r0!, {r4-r7}
                mov     r4, r8
                mov     r5, r9
                mov     r6, r10
                mov     r7, r11
                stmia   r0!, {r4-r7}
                #else
                stmdb   r0!, {r4-r11}
                ldr     r2, [r1]
                str     r0, [r2]
                #endif
/* 恢复现场 */
__RESTORE       str     r3, [r1]
                ldr     r0, [r3]
                #if (__CMX_ISA == 6)
                adds    r0, #16
                ldmia   r0!, {r4-r7}
                mov     r11, r7
                mov     r10, r6
                mov     r9, r5
                mov     r8, r4
                mov     r1, r0
                subs    r1, #32
                ldmia   r1!, {r4-r7}
                #else
                ldmia   r0!, {r4-r11}
                #endif
                #if (MCUCFG_ASPEN_LSPEN == 1)
                vldmia  r0!, {s16-s31}
                #endif
                msr     psp, r0
/* 返回 */
__RETURN        pop     {pc}

                ALIGN
}


/* 中断挂起服务装载器 */
#if (MCUCFG_PENDSVFIFO_DEPTH > 0)
__ASM void mPendSV_FIFOLoader(void *sv)
{
                IMPORT  mPendSV_FIFO_P0
                IMPORT  mPendSV_FIFO_P1
                IMPORT  m_sign_fifo
                THUMB
/* FIFO选择 */
                ldr     r3, =m_sign_fifo
                ldrb    r3, [r3]
                #if (__CMX_ISA == 6)
                cmp     r3, #0
                beq     __FIFO1
                #else
                cbz     r3, __FIFO1
                #endif
__FIFO0         ldr     r1, =mPendSV_FIFO_P0
                b       __FIFOPTRINC
__FIFO1         ldr     r1, =mPendSV_FIFO_P1

/* FIFO指针递增 */
__FIFOPTRINC    /* 1、互斥访问指令 */
                #if (MCUCFG_PENDSVFIFO_MUTEX == 1)
__LOOP          ldrex   r2, [r1]
                adds    r2, #4
                strex   r3, r2, [r1]
                cmp     r3, #0
                bne     __LOOP

                /* 2、互斥访问机制 */
                #elif (MCUCFG_PENDSVFIFO_MUTEX == 2)
                IMPORT  mPendSV_FIFO_P2
                IMPORT  m_sign_load
                #define rx r6
                push    {r0, r4}
                mov     r0, rx
                ldr     r3, =m_sign_load
                ldrb    r4, [r3]
                movs    r2, #1
                strb    r2, [r3]

__LOOP          mov     rx, r1
                ldr     r2, [rx]
                adds    r2, #4
                str     r2, [rx]
                cmp     rx, r1
                bne     __LOOP

                strb    r4, [r3]

                #if (__CMX_ISA == 6)
                cmp     r4, #0
                beq     __RESrx
                #else
                cbz     r4, __RESrx
                #endif
                ldr     rx, =mPendSV_FIFO_P2
                b       __OVER
__RESrx         mov     rx, r0
__OVER          pop     {r0, r4}
                #undef rx
                /* 3、关闭总中断 */
                #elif (MCUCFG_PENDSVFIFO_MUTEX == 3)
                mrs     r3, primask
                cpsid   i
                ldr     r2, [r1]
                adds    r2, #4
                str     r2, [r1]
                msr     primask, r3
                #endif
/* 装载 */
                str     r0, [r2]
                bx      lr

                ALIGN
}
#endif


/*
 * IAR Compiler
 * GNU Compiler
 * Arm Compiler 6.6 LTM / above 6.10.1 (armclang)
 */
#elif ((defined ( __GNUC__   )) \
   ||  (defined ( __ICCARM__ )) \
   ||  (defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)))

#if !defined (__ICCARM__)
s_u8_t sPendSV_Handler(void);
extern s_tasknode_tsp s_task_news;
#else
#include "os_handler.c"
#endif

/* PendSV软中断 */
void OS_PendSV_Handler(void)
{
        #if !defined (__ICCARM__)
        __ASM volatile(".THUMB");
        #endif
        __ASM volatile(
                "push    {lr} \n"
                "bl      sPendSV_Handler \n"
/* 直接返回吗？*/
                #if ((__CMX_ISA == 6) || defined (__ICCARM__))
                "cmp     r0, #0 \n"
                "beq     __RETURN \n"
                #else
                "cbz     r0, __RETURN \n"
                #endif
                "isb \n"
/* 保护现场吗？*/
                "ldr     r1, =s_task_current \n"
                "subs    r0, #1 \n"
                #if ((__CMX_ISA == 6) || defined (__ICCARM__))
                "cmp     r0, #0 \n"
                "beq     __RESTORE \n"
                #else
                "cbz     r0, __RESTORE \n"
                #endif
                "mrs     r0, psp \n"
/* 任务PC监控 */
                #if (SYSCFG_TASKPC_MONITOR == 1)
                "ldr     r2, =s_sign_taskmgr \n"
                "ldrb    r2, [r2] \n"
                #if ((__CMX_ISA == 6) || defined (__ICCARM__))
                "cmp     r2, #0 \n"
                "beq     __PROTECTING \n"
                #else
                "cbz     r2, __PROTECTING \n"
                #endif
                "ldr     r2, [r0,#24] \n"
                "ldr     r3, =s_pc \n"
                "str     r2, [r3] \n"
                #endif
/* 保护现场 */
"__PROTECTING: \n"
                #if (MCUCFG_ASPEN_LSPEN == 1)
                "vstmdb  r0!, {s16-s31} \n"
                #endif
                #if (__CMX_ISA == 6)
                "subs    r0, #32 \n"
                "ldr     r2, [r1] \n"
                "str     r0, [r2] \n"
                "stmia   r0!, {r4-r7} \n"
                "mov     r4, r8 \n"
                "mov     r5, r9 \n"
                "mov     r6, r10 \n"
                "mov     r7, r11 \n"
                "stmia   r0!, {r4-r7} \n"
                #else
                "stmdb   r0!, {r4-r11} \n"
                "ldr     r2, [r1] \n"
                "str     r0, [r2] \n"
                #endif
/* 恢复现场 */
"__RESTORE:      ldr     r3, =s_task_news \n"
                "ldr     r3, [r3] \n"
                "str     r3, [r1] \n"
                "ldr     r0, [r3] \n"
                #if (__CMX_ISA == 6)
                "adds    r0, #16 \n"
                "ldmia   r0!, {r4-r7} \n"
                "mov     r11, r7 \n"
                "mov     r10, r6 \n"
                "mov     r9, r5 \n"
                "mov     r8, r4 \n"
                "mov     r1, r0 \n"
                "subs    r1, #32 \n"
                "ldmia   r1!, {r4-r7} \n"
                #else
                "ldmia   r0!, {r4-r11} \n"
                #endif
                #if (MCUCFG_ASPEN_LSPEN == 1)
                "vldmia  r0!, {s16-s31} \n"
                #endif
                "msr     psp, r0 \n"
/* 返回 */
"__RETURN:       pop     {pc}"
        );
        #if !defined (__ICCARM__)
        __ASM volatile(".ALIGN");
        #endif
}


/* 中断挂起服务装载器 */
#if (MCUCFG_PENDSVFIFO_DEPTH > 0)
void mPendSV_FIFOLoader(void *sv)
{
        #if !defined (__ICCARM__)
        __ASM volatile(".THUMB");
        #endif
        __ASM volatile(
/* FIFO选择 */
                "ldr     r3, =m_sign_fifo \n"
                "ldrb    r3, [r3] \n"
                #if ((__CMX_ISA == 6) || defined (__ICCARM__))
                "cmp     r3, #0 \n"
                "beq     __FIFO1 \n"
                #else
                "cbz     r3, __FIFO1 \n"
                #endif
"__FIFO0:       ldr     r1, =mPendSV_FIFO_P0 \n"
                "b       __FIFOPTRINC \n"
"__FIFO1:       ldr     r1, =mPendSV_FIFO_P1 \n"

/* FIFO指针递增 */
"__FIFOPTRINC: \n"
                /* 1、互斥访问指令 */
                #if (MCUCFG_PENDSVFIFO_MUTEX == 1)
"__LOOP:         ldrex   r2, [r1] \n"
                "adds    r2, #4 \n"
                "strex   r3, r2, [r1] \n"
                "cmp     r3, #0 \n"
                "bne     __LOOP \n"

                /* 2、互斥访问机制 *//// rx=r6
                #elif (MCUCFG_PENDSVFIFO_MUTEX == 2)
                "push    {r0, r4} \n"
                "mov     r0, r6 \n"   // 保护-rx
                "ldr     r3, =m_sign_load \n"
                "ldrb    r4, [r3] \n" // 保护-m_sign_load
                "movs    r2, #1 \n"
                "strb    r2, [r3] \n" // 设置-m_sign_load

"__LOOP:         mov     r6, r1 \n"
                "ldr     r2, [r6] \n"
                "adds    r2, #4 \n"
                "str     r2, [r6] \n"
                "cmp     r6, r1 \n"
                "bne     __LOOP \n"

                "strb    r4, [r3] \n" // 恢复-m_sign_load
                /**
                 \brief      重设或恢复-rx
                 \details    if(原m_sign_load==0){恢复-rx;} // 本次的__LOOP未打断其它中断的__LOOP
                             if(原m_sign_load==1){重设-rx;} // 本次的__LOOP已打断其它中断的__LOOP
                */
                #if ((__CMX_ISA == 6) || defined (__ICCARM__))
                "cmp     r4, #0 \n"
                "beq     __RESrx \n"
                #else
                "cbz     r4, __RESrx \n"
                #endif
                "ldr     r6, =mPendSV_FIFO_P2 \n" // 重设-rx
                "b       __OVER \n"
"__RESrx:        mov     r6, r0 \n" // 恢复-rx
"__OVER:         pop     {r0, r4} \n"

                /* 3、关闭总中断 */
                #elif (MCUCFG_PENDSVFIFO_MUTEX == 3)
                "mrs     r3, primask \n"
                "cpsid   i \n"
                "ldr     r2, [r1] \n"
                "adds    r2, #4 \n"
                "str     r2, [r1] \n"
                "msr     primask, r3 \n"
                #endif
/* 装载 */
                "str     r0, [r2] \n"
                "bx      lr"
        );
        #if !defined (__ICCARM__)
        __ASM volatile(".ALIGN");
        #endif
}
#endif


/*
 * Unknown Compiler
 */
#else

    #error Unknown compiler.
#endif

#endif
